home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / tk2.3 / dist / tkBitmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-24  |  14.0 KB  |  494 lines

  1. /* 
  2.  * tkBitmap.c --
  3.  *
  4.  *    This file maintains a database of read-only bitmaps for the Tk
  5.  *    toolkit.  This allows bitmaps to be shared between widgets and
  6.  *    also avoids interactions with the X server.
  7.  *
  8.  * Copyright 1990-1992 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkBitmap.c,v 1.16 92/08/24 09:45:43 ouster Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include "tkConfig.h"
  23. #include "tk.h"
  24.  
  25. /*
  26.  * The includes below are for pre-defined bitmaps.
  27.  */
  28.  
  29. #include "bitmaps/gray50"
  30. #include "bitmaps/gray25"
  31.  
  32. /*
  33.  * One of the following data structures exists for each bitmap that is
  34.  * currently in use.  Each structure is indexed with both "idTable" and
  35.  * "nameTable".
  36.  */
  37.  
  38. typedef struct {
  39.     Pixmap bitmap;        /* X identifier for bitmap.  None means this
  40.                  * bitmap was created by Tk_DefineBitmap
  41.                  * and it isn't currently in use. */
  42.     unsigned int width, height;    /* Dimensions of bitmap. */
  43.     Display *display;        /* Display for which bitmap is valid. */
  44.     int refCount;        /* Number of active uses of bitmap. */
  45.     Tcl_HashEntry *hashPtr;    /* Entry in nameTable for this structure
  46.                  * (needed when deleting). */
  47. } TkBitmap;
  48.  
  49. /*
  50.  * Hash table to map from a textual description of a bitmap to the
  51.  * TkBitmap record for the bitmap, and key structure used in that
  52.  * hash table:
  53.  */
  54.  
  55. static Tcl_HashTable nameTable;
  56. typedef struct {
  57.     Tk_Uid name;        /* Textual name for desired bitmap. */
  58.     Display *display;        /* Display for which bitmap will be used. */
  59. } NameKey;
  60.  
  61. /*
  62.  * Hash table that maps from bitmap identifiers to the TkBitmap structure
  63.  * for the bitmap.  This table is indexed by Bitmap ids, and is used by
  64.  * Tk_FreeBitmap.
  65.  */
  66.  
  67. static Tcl_HashTable idTable;
  68.  
  69. /*
  70.  * For each call to Tk_DefineBitmap one of the following structures is
  71.  * created to hold information about the bitmap.
  72.  */
  73.  
  74. typedef struct {
  75.     char *source;        /* Bits for bitmap. */
  76.     unsigned int width, height;    /* Dimensions of bitmap. */
  77. } PredefBitmap;
  78.  
  79. /*
  80.  * Hash table create by Tk_DefineBitmap to map from a name to a
  81.  * collection of in-core data about a bitmap.  The table is
  82.  * indexed by the address of the data for the bitmap, and the entries
  83.  * contain pointers to PredefBitmap structures.
  84.  */
  85.  
  86. static Tcl_HashTable predefTable;
  87.  
  88. /*
  89.  * Hash table used by Tk_GetBitmapFromData to map from a collection
  90.  * of in-core data about a bitmap to a Tk_Uid giving an automatically-
  91.  * generated name for the bitmap:
  92.  */
  93.  
  94. static Tcl_HashTable dataTable;
  95. typedef struct {
  96.     char *source;        /* Bitmap bits. */
  97.     unsigned int width, height;    /* Dimensions of bitmap. */
  98. } DataKey;
  99.  
  100. static int initialized = 0;    /* 0 means static structures haven't been
  101.                  * initialized yet. */
  102.  
  103. /*
  104.  * Forward declarations for procedures defined in this file:
  105.  */
  106.  
  107. static void        BitmapInit _ANSI_ARGS_((void));
  108.  
  109. /*
  110.  *----------------------------------------------------------------------
  111.  *
  112.  * Tk_GetBitmap --
  113.  *
  114.  *    Given a string describing a bitmap, locate (or create if necessary)
  115.  *    a bitmap that fits the description.
  116.  *
  117.  * Results:
  118.  *    The return value is the X identifer for the desired bitmap
  119.  *    (i.e. a Pixmap with a single plane), unless string couldn't be
  120.  *    parsed correctly.  In this case, None is returned and an error
  121.  *    message is left in interp->result.  The caller should never
  122.  *    modify the bitmap that is returned, and should eventually call
  123.  *    Tk_FreeBitmap when the bitmap is no longer needed.
  124.  *
  125.  * Side effects:
  126.  *    The bitmap is added to an internal database with a reference count.
  127.  *    For each call to this procedure, there should eventually be a call
  128.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  129.  *    aren't needed anymore.
  130.  *
  131.  *----------------------------------------------------------------------
  132.  */
  133.  
  134. Pixmap
  135. Tk_GetBitmap(interp, tkwin, string)
  136.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  137.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  138.     Tk_Uid string;        /* Description of bitmap.  See manual entry
  139.                  * for details on legal syntax. */
  140. {
  141.     NameKey key;
  142.     Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
  143.     register TkBitmap *bitmapPtr;
  144.     PredefBitmap *predefPtr;
  145.     int new;
  146.     Pixmap bitmap;
  147.     unsigned int width, height;
  148.     int dummy2;
  149.  
  150.     if (!initialized) {
  151.     BitmapInit();
  152.     }
  153.  
  154.     key.name = string;
  155.     key.display = Tk_Display(tkwin);
  156.     nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &key, &new);
  157.     if (!new) {
  158.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
  159.     bitmapPtr->refCount++;
  160.     return bitmapPtr->bitmap;
  161.     }
  162.  
  163.     /*
  164.      * No suitable bitmap exists.  Create a new bitmap from the
  165.      * information contained in the string.  If the string starts
  166.      * with "@" then the rest of the string is a file name containing
  167.      * the bitmap.  Otherwise the string must refer to a bitmap
  168.      * defined by a call to Tk_DefineBitmap.
  169.      */
  170.  
  171.     if (*string == '@') {
  172.     string = Tcl_TildeSubst(interp, string + 1);
  173.     if (string == NULL) {
  174.         goto error;
  175.     }
  176.     if (XReadBitmapFile(key.display, RootWindowOfScreen(Tk_Screen(tkwin)),
  177.         string, &width, &height, &bitmap, &dummy2, &dummy2)
  178.         != BitmapSuccess) {
  179.         Tcl_AppendResult(interp, "error reading bitmap file \"", string,
  180.             "\"", (char *) NULL);
  181.         goto error;
  182.     }
  183.     } else {
  184.     predefHashPtr = Tcl_FindHashEntry(&predefTable, string);
  185.     if (predefHashPtr == NULL) {
  186.         Tcl_AppendResult(interp, "bitmap \"", string,
  187.             "\" not defined", (char *) NULL);
  188.         goto error;
  189.     }
  190.     predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr);
  191.     width = predefPtr->width;
  192.     height = predefPtr->height;
  193.     bitmap = XCreateBitmapFromData(key.display,
  194.         DefaultRootWindow(key.display), predefPtr->source,
  195.         width, height);
  196.     }
  197.  
  198.     /*
  199.      * Add information about this bitmap to our database.
  200.      */
  201.  
  202.     bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
  203.     bitmapPtr->bitmap = bitmap;
  204.     bitmapPtr->width = width;
  205.     bitmapPtr->height = height;
  206.     bitmapPtr->display = key.display;
  207.     bitmapPtr->refCount = 1;
  208.     bitmapPtr->hashPtr = nameHashPtr;
  209.     idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) bitmapPtr->bitmap,
  210.         &new);
  211.     if (!new) {
  212.     panic("bitmap already registered in Tk_GetBitmap");
  213.     }
  214.     Tcl_SetHashValue(nameHashPtr, bitmapPtr);
  215.     Tcl_SetHashValue(idHashPtr, bitmapPtr);
  216.     return bitmapPtr->bitmap;
  217.  
  218.     error:
  219.     Tcl_DeleteHashEntry(nameHashPtr);
  220.     return None;
  221. }
  222.  
  223. /*
  224.  *----------------------------------------------------------------------
  225.  *
  226.  * Tk_DefineBitmap --
  227.  *
  228.  *    This procedure associates a textual name with a binary bitmap
  229.  *    description, so that the name may be used to refer to the
  230.  *    bitmap in future calls to Tk_GetBitmap.
  231.  *
  232.  * Results:
  233.  *    A standard Tcl result.  If an error occurs then TCL_ERROR is
  234.  *    returned and a message is left in interp->result.
  235.  *
  236.  * Side effects:
  237.  *    "Name" is entered into the bitmap table and may be used from
  238.  *    here on to refer to the given bitmap.
  239.  *
  240.  *----------------------------------------------------------------------
  241.  */
  242.  
  243. int
  244. Tk_DefineBitmap(interp, name, source, width, height)
  245.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  246.     Tk_Uid name;        /* Name to use for bitmap.  Must not already
  247.                  * be defined as a bitmap. */
  248.     char *source;        /* Address of bits for bitmap. */
  249.     unsigned int width;        /* Width of bitmap. */
  250.     unsigned int height;    /* Height of bitmap. */
  251. {
  252.     int new;
  253.     Tcl_HashEntry *predefHashPtr;
  254.     PredefBitmap *predefPtr;
  255.  
  256.     if (!initialized) {
  257.     BitmapInit();
  258.     }
  259.  
  260.     predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new);
  261.     if (!new) {
  262.         Tcl_AppendResult(interp, "bitmap \"", name,
  263.         "\" is already defined", (char *) NULL);
  264.     return TCL_ERROR;
  265.     }
  266.     predefPtr = (PredefBitmap *) malloc(sizeof(PredefBitmap));
  267.     predefPtr->source = source;
  268.     predefPtr->width = width;
  269.     predefPtr->height = height;
  270.     Tcl_SetHashValue(predefHashPtr, predefPtr);
  271.     return TCL_OK;
  272. }
  273.  
  274. /*
  275.  *--------------------------------------------------------------
  276.  *
  277.  * Tk_NameOfBitmap --
  278.  *
  279.  *    Given a bitmap, return a textual string identifying the
  280.  *    bitmap.
  281.  *
  282.  * Results:
  283.  *    The return value is the string name associated with bitmap.
  284.  *
  285.  * Side effects:
  286.  *    None.
  287.  *
  288.  *--------------------------------------------------------------
  289.  */
  290.  
  291. Tk_Uid
  292. Tk_NameOfBitmap(bitmap)
  293.     Pixmap bitmap;            /* Bitmap whose name is wanted. */
  294. {
  295.     Tcl_HashEntry *idHashPtr;
  296.     TkBitmap *bitmapPtr;
  297.  
  298.     if (!initialized) {
  299.     unknown:
  300.     panic("Tk_NameOfBitmap received unknown bitmap argument");
  301.     }
  302.  
  303.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
  304.     if (idHashPtr == NULL) {
  305.     goto unknown;
  306.     }
  307.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  308.     return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
  309. }
  310.  
  311. /*
  312.  *--------------------------------------------------------------
  313.  *
  314.  * Tk_SizeOfBitmap --
  315.  *
  316.  *    Given a bitmap managed by this module, returns the width
  317.  *    and height of the bitmap..
  318.  *
  319.  * Results:
  320.  *    The words at *widthPtr and *heightPtr are filled in with
  321.  *    the dimenstions of bitmap.
  322.  *
  323.  * Side effects:
  324.  *    If bitmap isn't managed by this module then the procedure
  325.  *    panics..
  326.  *
  327.  *--------------------------------------------------------------
  328.  */
  329.  
  330. void
  331. Tk_SizeOfBitmap(bitmap, widthPtr, heightPtr)
  332.     Pixmap bitmap;            /* Bitmap whose size is wanted. */
  333.     unsigned int *widthPtr;        /* Store bitmap width here. */
  334.     unsigned int *heightPtr;        /* Store bitmap height here. */
  335. {
  336.     Tcl_HashEntry *idHashPtr;
  337.     TkBitmap *bitmapPtr;
  338.  
  339.     if (!initialized) {
  340.     unknownBitmap:
  341.     panic("Tk_SizeOfBitmap received unknown bitmap argument");
  342.     }
  343.  
  344.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
  345.     if (idHashPtr == NULL) {
  346.     goto unknownBitmap;
  347.     }
  348.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  349.     *widthPtr = bitmapPtr->width;
  350.     *heightPtr = bitmapPtr->height;
  351. }
  352.  
  353. /*
  354.  *----------------------------------------------------------------------
  355.  *
  356.  * Tk_FreeBitmap --
  357.  *
  358.  *    This procedure is called to release a bitmap allocated by
  359.  *    Tk_GetBitmap or TkGetBitmapFromData.
  360.  *
  361.  * Results:
  362.  *    None.
  363.  *
  364.  * Side effects:
  365.  *    The reference count associated with bitmap is decremented, and
  366.  *    it is officially deallocated if no-one is using it anymore.
  367.  *
  368.  *----------------------------------------------------------------------
  369.  */
  370.  
  371. void
  372. Tk_FreeBitmap(bitmap)
  373.     Pixmap bitmap;            /* Bitmap to be released. */
  374. {
  375.     Tcl_HashEntry *idHashPtr;
  376.     register TkBitmap *bitmapPtr;
  377.  
  378.     if (!initialized) {
  379.     panic("Tk_FreeBitmap called before Tk_GetBitmap");
  380.     }
  381.  
  382.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
  383.     if (idHashPtr == NULL) {
  384.     panic("Tk_FreeBitmap received unknown bitmap argument");
  385.     }
  386.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  387.     bitmapPtr->refCount--;
  388.     if (bitmapPtr->refCount == 0) {
  389.     XFreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
  390.     Tcl_DeleteHashEntry(idHashPtr);
  391.     Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
  392.     ckfree((char *) bitmapPtr);
  393.     }
  394. }
  395.  
  396. /*
  397.  *----------------------------------------------------------------------
  398.  *
  399.  * Tk_GetBitmapFromData --
  400.  *
  401.  *    Given a description of the bits for a bitmap, make a bitmap that
  402.  *    has the given properties.
  403.  *
  404.  * Results:
  405.  *    The return value is the X identifer for the desired bitmap
  406.  *    (a one-plane Pixmap), unless it couldn't be created properly.
  407.  *    In this case, None is returned and an error message is left in
  408.  *    interp->result.  The caller should never modify the bitmap that
  409.  *    is returned, and should eventually call Tk_FreeBitmap when the
  410.  *    bitmap is no longer needed.
  411.  *
  412.  * Side effects:
  413.  *    The bitmap is added to an internal database with a reference count.
  414.  *    For each call to this procedure, there should eventually be a call
  415.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  416.  *    aren't needed anymore.
  417.  *
  418.  *----------------------------------------------------------------------
  419.  */
  420.  
  421.     /* ARGSUSED */
  422. Pixmap
  423. Tk_GetBitmapFromData(interp, tkwin, source, width, height)
  424.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  425.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  426.     char *source;        /* Bitmap data for bitmap shape. */
  427.     unsigned int width, height;    /* Dimensions of bitmap. */
  428. {
  429.     DataKey key;
  430.     Tcl_HashEntry *dataHashPtr;
  431.     Tk_Uid name = NULL;        /* Initialization need only to prevent
  432.                  * compiler warning. */
  433.     int new;
  434.     static autoNumber = 0;
  435.     char string[20];
  436.  
  437.     if (!initialized) {
  438.     BitmapInit();
  439.     }
  440.  
  441.     key.source = source;
  442.     key.width = width;
  443.     key.height = height;
  444.     dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &key, &new);
  445.     if (!new) {
  446.     name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
  447.     } else {
  448.     autoNumber++;
  449.     sprintf(string, "_tk%d", autoNumber);
  450.     name = Tk_GetUid(string);
  451.     Tcl_SetHashValue(dataHashPtr, name);
  452.     if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
  453.         Tcl_DeleteHashEntry(dataHashPtr);
  454.         return TCL_ERROR;
  455.     }
  456.     }
  457.     return Tk_GetBitmap(interp, tkwin, name);
  458. }
  459.  
  460. /*
  461.  *----------------------------------------------------------------------
  462.  *
  463.  * BitmapInit --
  464.  *
  465.  *    Initialize the structures used for bitmap management.
  466.  *
  467.  * Results:
  468.  *    None.
  469.  *
  470.  * Side effects:
  471.  *    Read the code.
  472.  *
  473.  *----------------------------------------------------------------------
  474.  */
  475.  
  476. static void
  477. BitmapInit()
  478. {
  479.     Tcl_Interp *dummy;
  480.  
  481.     dummy = Tcl_CreateInterp();
  482.     initialized = 1;
  483.     Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
  484.     Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
  485.     Tcl_InitHashTable(&predefTable, TCL_ONE_WORD_KEYS);
  486.     Tcl_InitHashTable(&idTable, TCL_ONE_WORD_KEYS);
  487.  
  488.     Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), gray50_bits, gray50_width,
  489.         gray50_height);
  490.     Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), gray25_bits, gray25_width,
  491.         gray25_height);
  492.     Tcl_DeleteInterp(dummy);
  493. }
  494.